#include "gwbase/base/thread.h"
#include "gwbase/base/logging.h"
#include <sys/types.h>
#include <sys/syscall.h>
#include <cassert>

namespace dicom {
namespace {

struct ThreadData {
  std::string name;
  Thread::ThreadFunc func;
  boost::shared_ptr<pid_t> tid;
};

void* GenericThreadRoutine(void *arg) {
  assert (arg != NULL);
  struct ThreadData* td = static_cast<struct ThreadData*>(arg);
  *td->tid = gettid();
  LOG_INFO << "thread [" << td->name << "] started!";
  td->func();
  LOG_INFO << "thread [" << td->name << "] terminated!";
  delete td;
  return 0;
}

}

pid_t gettid()
{
  return static_cast<pid_t>(::syscall(SYS_gettid));
}

Thread::Thread(const ThreadFunc& func, const std::string& name)
  : func_(func), name_(name), tid_(new pid_t(0)),
    started_(false), joined_(false) { }

    Thread::~Thread() { 
      if (started_ && !joined_) {
        pthread_detach(pthread_);
      }
    }

void Thread::Start() {
  assert (!started_);
  started_ = true;
  ThreadData* td = new ThreadData();
  td->name = name_;
  td->func = func_;
  td->tid = tid_;
  if (pthread_create(&pthread_, NULL, GenericThreadRoutine, td)) {
    started_ = false;
    delete td;
  }
}

int Thread::Join() {
  assert (started_);
  assert (!joined_);
  joined_ = true;
  return pthread_join(pthread_, NULL);
}

}
